from datetime import datetime, timedelta
from pathlib import Path
import json
from consts import DEFAULT_CONFIG_PATH,BASE_API_URL,ACCESS_TOKEN_FILE_NAME,ACCESS_TOKEN_EXPIRE_SECOND
from config import OFFICIAL_APIS
import requests
from typing import Optional,Dict


CUR_FILE = Path(__file__)
TOKEN_PATH = CUR_FILE.parent.joinpath(ACCESS_TOKEN_FILE_NAME)




class TokenInfo:
    def __init__(self, token: str, expire_time: float):
        self.token = token
        self.expire_time = expire_time

    def is_expired(self) -> bool:
        """检查 token 是否过期"""
        return datetime.now().timestamp() >= self.expire_time

    def to_dict(self) -> dict:
        """将 token 信息转换为字典"""
        return {
            'token': self.token,
            'expire_time': self.expire_time
        }
    

class TokenManager:

    # 类属性定义
    corpid: str
    agentid: str
    corpsecret: str
    token_path: Path
    _token_key: str
    _getApiTokenUrl: str
    proxies: Optional[Dict[str, str]]

    def __init__(self, corpid: str, agentid: str, corpsecret: str,proxies: Optional[Dict[str, str]] ):
        self.corpid = corpid
        self.agentid = agentid
        self.corpsecret = corpsecret
        self.proxies = proxies
        self.token_path = TOKEN_PATH
        self._token_key = f"{corpid}_{agentid}"  # 生成唯一的 token 键
        self._getApiTokenUrl = BASE_API_URL.format(OFFICIAL_APIS.get('GET_ACCESS_TOKEN').format(self.corpid,self.corpsecret)) 

    def get_assess_token(self) -> str:
        """获取 access token，优先从文件中读取，如果不存在则调用接口获取。"""
        try:
            token_dict = json.loads(self.token_path.read_text())
        except FileNotFoundError:
            # 文件不存在，重新获取 token
            return self.__get_access_token()
        else:
            return self._validate_token(token_dict)

    def _validate_token(self, token_dict: dict) -> str:
        try:
            token_info = TokenInfo(**token_dict[self._token_key])
        except KeyError:
            # token 不存在，重新获取
            return self.__get_access_token()
        else:
            if token_info.is_expired():
                # token 过期，重新获取
                return self.__get_access_token( )
            return token_info.token

    def __get_access_token(self) -> str:
        """调用接口获取新的 access token。"""
        res = requests.get(self._getApiTokenUrl,proxies=self.proxies).json()
        
        if res.get('errcode') == 0:
            token = res.get('access_token')
            self._update_token(token)
            return token
        else:
            raise Exception(f"Token 请求失败，原因：{res.get('errmsg', '无法获取 token')}")

    def _update_token(self, token: str):
        """更新 token 到文件中"""
        expire_time = datetime.now().timestamp() + ACCESS_TOKEN_EXPIRE_SECOND  # 设置过期时间为 2 小时
        token_info = TokenInfo(token, expire_time)
        token_dict = {self._token_key: token_info.to_dict()}
        self.token_path.write_text(json.dumps(token_dict))
